package cn.yyh.test;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;

/**
 * @ClassName: WebApplication
 * @Description:
 * @Author: yyh
 * @Date: 2020/8/11 13:52
 * @Version: 1.0
 */
@SpringBootApplication
public class WebApplication {

    public static void main(String[] args) {
        SpringApplication.run(WebApplication.class, args);
    }

    @RestController
    @RequestMapping("/test")
    public class WebController {

        @Resource(name = "ex")
        private ExecutorService executor;
        @Autowired
        private TestAsync testAsync;

        /**
         * 导入
         *
         * @param multipartFile
         * @throws Exception
         */
        @RequestMapping("/upload")
        public void test(@RequestParam("file") MultipartFile multipartFile) throws Exception {
            ImportParams params = new ImportParams();
            params.setHeadRows(1);

            List<User> userList = ExcelImportUtil.importExcel(multipartFile.getInputStream(), User.class, params);

            userList.forEach(o -> System.out.println(o));
        }

        /**
         * 导出
         *
         * @param
         * @throws Exception
         */
        @GetMapping ("/testOut")
        public void testOut(HttpServletResponse response) throws Exception {
            List<User> userList = new ArrayList(){{
                add(new User("1",1));
                add(new User("2",2));
                add(new User("3",3));
                add(new User("4",4));
                add(new User("5",5));
            }};

            ExportParams exportParams = new ExportParams();
            exportParams.setTitle("123");
            exportParams.setSheetName("12333");
            Workbook workbook = ExcelExportUtil.exportExcel(exportParams, User.class, userList);
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-Disposition",
                    "attachment;filename=" + URLEncoder.encode("fileName.xls", "utf-8"));

            workbook.write(response.getOutputStream());

            System.out.println(userList);
        }

        @RequestMapping("/testThrea")
        public void test1() {
            executor.submit(() -> {
                System.out.println("函数 --> 消费线程");
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });

            executor.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("消费线程");
                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        @RequestMapping("/test2")
        public void test2() {

            testAsync.async();

            executor.submit(() -> {
                this.testSync1();
            });

            System.out.println(" 同步 ");

        }

        public void testSync1() {
            System.out.println(" 线程池异步 异步 ");
        }
    }

    /**
     * @Async 底层也是调用 executor.submit()方法
     * Spring容器启动初始化bean时，判断类中是否使用了@Async注解，创建切入点和切入点处理器，根据切入点创建代理，
     * 在调用@Async注解标注的方法时，会调用代理，执行切入点处理器invoke方法，将方法的执行提交给线程池，实现异步执行。
     * <p>
     * 需要注意的一个错误用法是，如果A类的a方法(没有标注@Async)调用它自己的b方法(标注@Async)是不会异步执行的，因为从a方法进入调用的都是它本身，不会进入代理。
     * https://cloud.tencent.com/developer/article/1426027 对应文章
     */
    @Component
    public static class TestAsync {
        @Async
        void async() {
            try {
                Thread.sleep(10000);
                System.out.println(" @Async 异步 ");

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

